package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailException;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.app.dto.ShopHeadInfoDto;
import com.yami.shop.bean.app.param.ShopAuditingParam;
import com.yami.shop.bean.dto.ShopCreateInfoDTO;
import com.yami.shop.bean.dto.ShopSigningInfoDTO;
import com.yami.shop.bean.dto.ShopUserRegisterDto;
import com.yami.shop.bean.enums.*;
import com.yami.shop.bean.event.*;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.*;
import com.yami.shop.bean.param.hnaPay.BaseTransForm;
import com.yami.shop.bean.vo.ShopDetailVO;
import com.yami.shop.common.bean.RequestKitBean;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.constants.CacheNames;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.i18n.LanguageEnum;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.util.*;
import com.yami.shop.config.HnaPayConfig;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.dao.ProductMapper;
import com.yami.shop.dao.ShopDetailMapper;
import com.yami.shop.dao.ShopWalletMapper;
import com.yami.shop.service.*;
import lombok.AllArgsConstructor;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author lgh on 2018/08/29.
 */
@Service
@AllArgsConstructor
public class ShopDetailServiceImpl extends ServiceImpl<ShopDetailMapper, ShopDetail> implements ShopDetailService {
    private final ShopDetailMapper shopDetailMapper;
    private final ShopAuditingService shopAuditingService;
    private final ShopWalletMapper shopWalletMapper;
    private final OfflineHandleEventService offlineHandleEventService;
    private final ProductMapper productMapper;
    private final ApplicationContext applicationContext;
    private final ApplicationEventPublisher eventPublisher;
    private final ShopCompanyService shopCompanyService;
    private final ShopBankCardService shopBankCardService;
    private final CategoryShopService categoryShopService;
    private final BrandShopService brandShopService;
    private final BlockchainShopService blockchainShopService;
    private final SupplierService supplierService;
    private final ProdCommService prodCommService;
    private final RequestKitBean requestKitBean;
    private final HnaPayConfig hnaPayConfig;
    private final ShopConfig shopConfig;
    private final DataWebService dataWebService;

    /**
     * 导出excel列（中文）
     */
    private final static String[] EXPORT_COL_CN = {"店铺名称", "商家名称", "店铺状态", "联系电话", "邮箱", "所在省份", "所在城市", "所在区域", "详细地址", "简介", "申请时间", "店铺类型", "签约起始时间", "签约终止时间", "经营范围", "统一社会信息代码", "企业名称", "住所", "法定代表人", "注册资本（万元）", "成立日期", "营业起始日期", "营业终止日期"};
    /**
     * 导出excel列（英文）
     */
    private final static String[] EXPORT_COL_EN = {"Store Name", "Business Name", "Shop Status", "Contact Phone", "Email", "Province", "City", "Area", "Detailed Address", "Introduction", "Application time", "Store Type", "Signature start time", "Signature end time", "Business scope", "Unified social information code", "Company name", "Domicile", "Legal representative", "Registered capital (10,000 yuan) ", "Establishment Date", "Business Start Date", "Business End Date"};

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopDetail.shopId")
    public void updateShopDetail(ShopDetail shopDetail) {
        this.checkShopInfo(shopDetail, false);
        // 若经纬度数据变更，需清空同城配送中的位置信息
        ShopDetail detailDb = this.getById(shopDetail.getShopId());
        if ((detailDb.getShopLng() != null && detailDb.getShopLat() != null) && (!detailDb.getShopLat().equals(shopDetail.getShopLat()) || !detailDb.getShopLng().equals(shopDetail.getShopLng()))) {
            applicationContext.publishEvent(new ClearPolygonPathEvent(shopDetail.getShopId()));
        }
        updateById(shopDetail);
    }

    @Override
    public double getDistance(Double lat, Double lng, Long shopId) {
        return shopDetailMapper.getDistance(lat, lng, shopId);
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public ShopDetail getShopDetailByShopId(Long shopId) {
        return shopDetailMapper.selectShopDetailById(shopId);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public void removeShopDetailCacheByShopId(Long shopId) {
    }

    @Override
    public ShopDetail getShopByMobile(String mobile) {
        return shopDetailMapper.getShopByMobile(mobile);
    }

    @Override
    public void updatePasswordByUserName(String username, String newPassword) {
        shopDetailMapper.updatePasswordByUserName(username, newPassword);
    }

    @Override
    public ShopDetail getShopDetailByUserId(String userId) {
        return shopDetailMapper.getShopDetailByUserId(userId);
    }

    /**
     * 申请开店
     *
     * @param userId
     * @param shopDetailParam
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyShop(String userId, ShopDetailParam shopDetailParam) {

        ShopDetail shopDetail = getShopDetailByUserId(userId);
        if (shopDetail != null && !Objects.equals(shopDetail.getShopStatus(), ShopStatus.NOTOPEN.value())) {
            // 您已经申请开启店铺,不能重新申请
            throw new YamiShopBindException("yami.cannot.reapply");
        }
        ShopDetail dbShopnameShop = shopDetailMapper.selectOne(new LambdaQueryWrapper<ShopDetail>().eq(ShopDetail::getShopName, shopDetailParam.getShopName()).ne(ShopDetail::getUserId, userId));
        if (dbShopnameShop != null) {
            // 店铺名称已存在
            throw new YamiShopBindException("yami.store.name.exist");
        }
        ShopDetail newShopDetail = BeanUtil.map(shopDetailParam, ShopDetail.class);

        Date now = new Date();
        // 如果是第一次申请开店
        if (shopDetail == null) {
            newShopDetail.setUserId(userId);
            newShopDetail.setCreateTime(now);
            newShopDetail.setShopOwner(userId);
            newShopDetail.setShopStatus(ShopStatus.NOTOPEN.value());
            newShopDetail.setIsDistribution(1);
        } else {
            newShopDetail.setShopId(shopDetail.getShopId());
            newShopDetail.setCreateTime(now);
        }


        newShopDetail.setUpdateTime(now);
        // 保存或更新
        saveOrUpdate(newShopDetail);
        // 清除缓存
        removeShopDetailCacheByShopId(newShopDetail.getShopId());

        // 插入一条审核记录
        ShopAuditing auditing = shopAuditingService.getShopAuditingByUserId(userId);
        if (auditing == null) {
            auditing = new ShopAuditing();
            auditing.setShopId(newShopDetail.getShopId());
            auditing.setUserId(userId);
            auditing.setCreateTime(new Date());
        }
        auditing.setStatus(AuditStatus.WAITAUDIT.value());
        auditing.setUpdateTime(new Date());
        shopAuditingService.saveOrUpdate(auditing);
        if (Objects.isNull(shopDetail)) {
            // 第一次申请开店,店铺员工表插入一个超级管理员
//            applicationContext.publishEvent(new ShopEmployeeSuperAdminEvent(newShopDetail));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean audit(ShopAuditingParam shopAuditingParam) {
        ShopAuditing dbShopAuditing = shopAuditingService.getOne(Wrappers.lambdaQuery(ShopAuditing.class).eq(ShopAuditing::getShopId, shopAuditingParam.getShopId()));
        if (Objects.isNull(dbShopAuditing)) {
            throw new YamiShopBindException("该店铺没有提交审核");
        }
        if (!Objects.equals(dbShopAuditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
            throw new YamiShopBindException("店铺不处于待审核状态");
        }
        Date now = new Date();
        ShopAuditing shopAuditing = new ShopAuditing();
        shopAuditing.setShopAuditingId(dbShopAuditing.getShopAuditingId());
        shopAuditing.setShopId(shopAuditingParam.getShopId());
        shopAuditing.setAuditorId(shopAuditingParam.getAuditorId());
        shopAuditing.setUpdateTime(now);
        shopAuditing.setStatus(shopAuditingParam.getStatus());
        shopAuditing.setRemarks(shopAuditingParam.getRemarks());
        // 获取店铺信息
        ShopDetail shopDetail = getById(shopAuditingParam.getShopId());

        // 审核不通过
        if (Objects.equals(shopAuditingParam.getStatus(), AuditStatus.FAILAUDIT.value())) {
            shopDetail.setShopStatus(ShopStatus.APPLYING.value());
        }
        // 审核通过
        else {
            shopDetail.setType(shopAuditingParam.getShopType());
            shopDetail.setContractStartTime(DateUtil.beginOfDay(shopAuditingParam.getContractStartTime()));
            shopDetail.setContractEndTime(getSaveEndOfDay(shopAuditingParam.getContractEndTime()));
            if (now.compareTo(shopDetail.getContractStartTime()) >= 0 && now.compareTo(shopDetail.getContractEndTime()) < 0) {
                // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
                shopDetail.setShopStatus(ShopStatus.OPEN.value());
            } else {
                // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
                shopDetail.setShopStatus(ShopStatus.STOP.value());
            }
            // 添加店铺钱包
            this.addShopInfo(shopAuditingParam.getShopId());

            // 新店初始化事件
            applicationContext.publishEvent(new OpenShopInitEvent(shopDetail));
            // 添加默认供应商
            saveSupplier(shopDetail);
            // 把商家自定义品牌添加为平台品牌
            brandShopService.updateCustomBrandToPlatformBrandByShopId(shopAuditingParam.getShopId());
            // 更新签约分类与品牌的状态
            categoryShopService.changeStatusByShopIdAndStatus(shopAuditingParam.getShopId(), SigningStatus.PENDING_REVIEW.value(), SigningStatus.SUCCESS.value());
            brandShopService.changeStatusByShopIdAndStatus(shopAuditingParam.getShopId(), SigningStatus.PENDING_REVIEW.value(), SigningStatus.SUCCESS.value());
            blockchainShopService.changeStatusByShopIdAndStatus(shopAuditingParam.getShopId(), SigningStatus.PENDING_REVIEW.value(), SigningStatus.SUCCESS.value());
        }
        shopAuditingService.updateById(shopAuditing);
        updateById(shopDetail);
        return true;
    }

    private void saveSupplier(ShopDetail shopDetail) {
        Supplier supplier = new Supplier();
        supplier.setShopId(shopDetail.getShopId());
        supplier.setStatus(1);
        supplier.setSupplierName("自采供应商");
        supplier.setCreateTime(new Date());
        supplier.setIsDefault(1);
        supplierService.save(supplier);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopDetail.shopId")
    public void offline(ShopDetail shopDetail, String offlineReason, Long sysUserId) {
        // 添加下线处理记录
        Date now = new Date();
        OfflineHandleEvent offlineHandleEvent = new OfflineHandleEvent();
        offlineHandleEvent.setHandleId(shopDetail.getShopId());
        offlineHandleEvent.setHandleType(OfflineHandleEventType.SHOP.getValue());
        offlineHandleEvent.setCreateTime(now);
        offlineHandleEvent.setOfflineReason(offlineReason);
        offlineHandleEvent.setHandlerId(sysUserId);
        offlineHandleEvent.setShopId(shopDetail.getShopId());
        offlineHandleEvent.setStatus(OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEvent.setUpdateTime(now);
        offlineHandleEventService.save(offlineHandleEvent);

        // 更新店铺状态为下线
        shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.OFFLINE.value());

        // 将该店铺所有的商品下线状态
        productMapper.offlineProdByShopIds(Collections.singletonList(shopDetail.getShopId()));

        // 发送店铺违规下线事件
        applicationContext.publishEvent(new ShopChangeStatusEvent(shopDetail.getShopId(), ShopStatus.OFFLINE));

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#offlineHandleEventAuditParam.handleId")
    public Boolean auditOfflineShop(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        ShopDetail shopDetail = getShopDetailByShopId(offlineHandleEventAuditParam.getHandleId());
        if (Objects.isNull(shopDetail)) {
            // 未找到店铺信息
            throw new YamiShopBindException("yami.store.not.exist");
        }
        if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AUDIT.value())) {
            // 店铺不处于待审核状态
            throw new YamiShopBindException("店铺已经审核，请刷新页面");
        }
        Date now = new Date();
        // 审核通过
        if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            if (now.compareTo(shopDetail.getContractStartTime()) >= 0 && now.compareTo(shopDetail.getContractEndTime()) < 0) {
                // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
                shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.OPEN.value());
            } else {
                // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
                shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.STOP.value());
            }
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.OFFLINE.value());
        }
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
        // 状态改变后清理缓存
        removeShopDetailCacheByShopId(shopDetail.getShopId());
        return true;
    }

    @Override
    public List<ShopHeadInfoDto> listHotShopsHead() {
        return shopDetailMapper.listHotShopsHead();
    }

    @Override
    public Page<ShopHeadInfoDto> searchShops(PageParam<ShopHeadInfoDto> page, ShopHeadInfoDto shopHeadInfoDto) {
        return shopDetailMapper.searchShops(page, shopHeadInfoDto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertDetail(ShopDetail shopDetail, Long count) {
        Date date = new Date();
        shopDetail.setShopStatus(1);
        shopDetail.setIsDistribution(1);
        shopDetail.setCreateTime(date);
        shopDetail.setUpdateTime(date);
        if ((this.checkMobile(shopDetail.getMobile(), null) + count) > 0) {
            // 该账号已存在，请重新输入
            throw new YamiShopBindException("yami.store.account.exist");
        }
        long nameCount = count(new LambdaQueryWrapper<ShopDetail>().eq(ShopDetail::getShopName, shopDetail.getShopName()).eq(ShopDetail::getShopStatus, 1).ne(ShopDetail::getShopId, shopDetail.getShopId()));
        if (nameCount > 0) {
            // 已有相同名称
            throw new YamiShopBindException("yami.shop.name.have.already");
        }
        shopDetailMapper.insert(shopDetail);
        // 创建店铺钱包
        ShopWallet shopWallet = new ShopWallet();
        shopWallet.setShopId(shopDetail.getShopId());
        shopWallet.setUnsettledAmount(0.0);
        shopWallet.setSettledAmount(0.0);
        shopWallet.setFreezeAmount(0.0);
        shopWallet.setTotalSettledAmount(0.0);
        shopWallet.setVersion(0L);
        shopWallet.setUpdateTime(new Date());
        shopWalletMapper.insert(shopWallet);
        // 店铺员工表插入一个超级管理员
//        applicationContext.publishEvent(new ShopEmployeeSuperAdminEvent(shopDetail));
    }

    @Override
    public Long checkMobile(String mobile, Long shopId) {
        return count(new LambdaQueryWrapper<ShopDetail>().eq(ShopDetail::getMobile, mobile).ne(Objects.nonNull(shopId), ShopDetail::getShopId, shopId));
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public void updatePasswordOrMobile(Long shopId, String password, String mobile, Long count) {
        ShopDetail shopDetail = new ShopDetail();
        shopDetail.setShopId(shopId);

        shopDetail.setPassword(password);
        if (Objects.nonNull(mobile)) {
            if ((this.checkMobile(shopDetail.getMobile(), shopId) + count) > 0) {
                // 该账号已存在，请重新输入
                throw new YamiShopBindException("yami.store.account.exist");
            }
            shopDetail.setMobile(mobile);
        }
        shopDetailMapper.updateById(shopDetail);
        // 店铺员工表更新超级管理员账号密码
        applicationContext.publishEvent(new UpdateShopSuperAdminAccountEvent(shopDetail));
    }

    @Override
    public void batchUpdateShopType(ShopTypeParam shopTypeParam) {
        List<Long> shopIds = shopTypeParam.getShopIds();
        Integer type = shopTypeParam.getType();
        // 修改店铺类型
        if (CollUtil.isEmpty(shopIds)) {
            // 未找到店铺信息
            throw new YamiShopBindException("yami.select.a.shop");
        }
        if (Objects.isNull(type)) {
            // 未找到店铺信息
            throw new YamiShopBindException("yami.select.only.shop.type");
        }
        shopDetailMapper.batchUpdateShopType(shopIds, type);
        this.removeCacheByShopIds(shopIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(Long shopId, Long employeeId) {
        Date now = new Date();
        ShopDetail shopDetail = this.getShopDetailByShopId(shopId);
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OPEN_AWAIT_AUDIT.value())) {
            throw new YamiShopBindException("yami.shop.auditing");
        }
        ShopAuditing oldAuditing = shopAuditingService.getOne(Wrappers.lambdaQuery(ShopAuditing.class).eq(ShopAuditing::getShopId, shopId));
        ShopAuditing shopAuditing = new ShopAuditing();
        shopAuditing.setShopId(shopId);
        shopAuditing.setUserId(employeeId.toString());
        shopAuditing.setStatus(AuditStatus.WAITAUDIT.value());
        shopAuditing.setUpdateTime(now);
        if (Objects.nonNull(oldAuditing)) {
            shopAuditing.setShopAuditingId(oldAuditing.getShopAuditingId());
            shopAuditingService.updateById(shopAuditing);
        } else {
            shopAuditing.setCreateTime(now);
            shopAuditingService.save(shopAuditing);
        }
        // 更新店铺状态为待审核
        shopDetailMapper.updateStatus(shopId, ShopStatus.OPEN_AWAIT_AUDIT.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void platformCreateShop(ShopCreateInfoDTO shopCreateInfoDTO, Long userId) {
        ShopUserRegisterDto shopUserRegisterDto = shopCreateInfoDTO.getShopUserRegisterInfo();
        // 保存店铺基本信息
        Date now = new Date();
        ShopDetail shopDetail = shopCreateInfoDTO.getShopDetail();
        this.checkShopInfo(shopDetail, true);
        shopDetail.setCreateTime(now);
        shopDetail.setUpdateTime(now);
        if (Objects.isNull(shopDetail.getContractStartTime()) || Objects.isNull(shopDetail.getContractEndTime())) {
            throw new YamiShopBindException("店铺签约时间不能为空");
        }
        shopDetail.setContractStartTime(DateUtil.beginOfDay(shopDetail.getContractStartTime()));
        shopDetail.setContractEndTime(this.getSaveEndOfDay(shopDetail.getContractEndTime()));
        if (now.compareTo(shopDetail.getContractStartTime()) >= 0 && now.compareTo(shopDetail.getContractEndTime()) < 0) {
            // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
            shopDetail.setShopStatus(ShopStatus.OPEN.value());
        } else {
            // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
            shopDetail.setShopStatus(ShopStatus.STOP.value());
        }
        // 店铺接收短信通知手机号
        shopDetail.setReceiveMobile(shopUserRegisterDto.getMobile());
        shopDetailMapper.insert(shopDetail);
        Long shopId = shopDetail.getShopId();
        // 初始化店铺数据
        addShopInfo(shopId);
        // 初始化店铺审核信息，平台端创建店铺默认为审核成功
        ShopAuditing shopAuditing = new ShopAuditing();
        shopAuditing.setShopId(shopId);
        shopAuditing.setAuditorId(userId);
        shopAuditing.setCreateTime(now);
        shopAuditing.setUpdateTime(now);
        shopAuditing.setStatus(AuditStatus.SUCCESSAUDIT.value());
        shopAuditingService.save(shopAuditing);
        // 添加默认供应商
        saveSupplier(shopDetail);
        // 保存店铺工商信息
        ShopCompany shopCompany = shopCreateInfoDTO.getShopCompany();
        shopCompany.setShopId(shopDetail.getShopId());
        shopCompany.setStatus(AuditStatus.SUCCESSAUDIT.value());
        shopCompanyService.saveInfo(shopCompany);
        // 保存店铺银行卡信息
        shopBankCardService.saveBatchByShopId(shopCreateInfoDTO.getShopBankCardList(), shopId);
        // 保存分类签约信息
        categoryShopService.insertBatchByShopId(shopCreateInfoDTO.getCategorySigningList(), shopId, SigningStatus.SUCCESS.value());
        // 保存品牌签约信息
        brandShopService.insertBatchByShopId(shopCreateInfoDTO.getBrandSigningList(), shopId, SigningStatus.SUCCESS.value());
        // 保存链平台签约信息
        List<BlockchainShop> lianSigningList = shopCreateInfoDTO.getLianSigningList();
        lianSigningList.forEach(s->{
            s.setShopCode(shopDetail.getChannelCode());
        });
        blockchainShopService.insertBatchByShopId(shopCreateInfoDTO.getLianSigningList(), shopId, SigningStatus.SUCCESS.value());
        // 店铺员工表插入一个超级管理员
        shopUserRegisterDto.setShopId(shopId);
        applicationContext.publishEvent(new ShopEmployeeSuperAdminEvent(shopUserRegisterDto));
        // api平台补api鉴权账号和api鉴权密码
        applicationContext.publishEvent(new BlockchainShopEvent(shopCreateInfoDTO.getLianSigningList(), shopId, shopDetail));
    }

    @Override
    public void updateStatus(Long shopId, Integer status) {
        shopDetailMapper.updateStatus(shopId, status);
    }
    @Override
    public void updateCheckAge(Long shopId, String checkAge) {
        ShopDetail newShopDetail = new ShopDetail();
        newShopDetail.setShopId(shopId);
        newShopDetail.setAgeCheck(checkAge);
        shopDetailMapper.updateById(newShopDetail);
    }

    @Override
    public void changeShopStatusByContractTime(Date now) {
        // 获取状态需要改变为停业状态的店铺id列表
        List<Long> shopIdsToStop = shopDetailMapper.listShopIdsOfStatusChangeToStopByContractTime(now);
        // 获取状态需要改变为营业状态的店铺id列表
        List<Long> shopIdsToOpen = shopDetailMapper.listShopIdsOfStatusChangeToOpenByContractTime(now);
        if (CollUtil.isEmpty(shopIdsToOpen) && CollUtil.isEmpty(shopIdsToStop)) {
            // 没有店铺状态需要改变
            return;
        }
        // 改变店铺状态
        if (CollUtil.isNotEmpty(shopIdsToOpen)) {
            shopDetailMapper.batchUpdateShopStatusByShopIds(shopIdsToOpen, ShopStatus.STOP.value(), ShopStatus.OPEN.value());
        }
        if (CollUtil.isNotEmpty(shopIdsToStop)) {
            shopDetailMapper.batchUpdateShopStatusByShopIds(shopIdsToStop, ShopStatus.OPEN.value(), ShopStatus.STOP.value());
        }
        // 状态发生变化的店铺id列表
        List<Long> changeShopIds = CollUtil.unionAll(shopIdsToStop, shopIdsToOpen);
        if (CollUtil.isEmpty(changeShopIds)) {
            return;
        }
        // 清除状态发生变化的店铺缓存信息
        List<String> keyList = new ArrayList<>();
        changeShopIds.forEach(shopId -> {
            keyList.add(CacheNames.SHOP_DETAIL_ID_KEY + CacheNames.UNION + shopId);
        });
        // 下架店铺的商品
        RedisUtil.deleteBatch(keyList);
        productMapper.offlineProdByShopIds(changeShopIds);
        // 在es更新店铺下的商品（用于刷新商品在es的appDisplay）
        this.updateProdByShopIds(changeShopIds);
    }

    /**
     * 根据店铺id列表删除缓存
     *
     * @param shopIds
     */
    private void removeCacheByShopIds(List<Long> shopIds) {
        List<String> keyList = new ArrayList<>();
        shopIds.forEach(shopId -> {
            keyList.add(CacheNames.SHOP_DETAIL_ID_KEY + CacheNames.UNION + shopId);
        });
        RedisUtil.deleteBatch(keyList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopSigningInfoDTO.shopId")
    public void updateSigningInfo(ShopSigningInfoDTO shopSigningInfoDTO) {
        ShopDetail oldShopDetail = shopDetailMapper.selectOne(Wrappers.lambdaQuery(ShopDetail.class).eq(ShopDetail::getShopId, shopSigningInfoDTO.getShopId()));
        ShopDetail newShopDetail = BeanUtil.map(oldShopDetail, ShopDetail.class);
        newShopDetail.setType(shopSigningInfoDTO.getType());
        newShopDetail.setContractStartTime(DateUtil.beginOfDay(shopSigningInfoDTO.getContractStartTime()));
        newShopDetail.setContractEndTime(getSaveEndOfDay(shopSigningInfoDTO.getContractEndTime()));
        // 当店铺状态处于营业中或者停业中时，店铺状态会受签约时间改变
        if (Objects.equals(newShopDetail.getShopStatus(), ShopStatus.OPEN.value()) || Objects.equals(newShopDetail.getShopStatus(), ShopStatus.STOP.value())) {
            Date now = new Date();
            // 记录店铺状态是否发生改变
            boolean isChangeStatus = false;
            if (now.compareTo(newShopDetail.getContractStartTime()) >= 0 && now.compareTo(newShopDetail.getContractEndTime()) < 0) {
                // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
                isChangeStatus = Objects.equals(oldShopDetail.getShopStatus(), ShopStatus.STOP.value());
                newShopDetail.setShopStatus(ShopStatus.OPEN.value());
                shopDetailMapper.updateById(newShopDetail);
            } else if (now.compareTo(newShopDetail.getContractStartTime()) < 0 || now.compareTo(newShopDetail.getContractEndTime()) >= 0) {
                // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
                isChangeStatus = Objects.equals(oldShopDetail.getShopStatus(), ShopStatus.OPEN.value());
                newShopDetail.setShopStatus(ShopStatus.STOP.value());
                shopDetailMapper.updateById(newShopDetail);
            }
            // 如果店铺状态发生变化
            if (isChangeStatus) {
                this.updateProdByShopIds(Collections.singletonList(newShopDetail.getShopId()));
            }
        }
        // 店铺违规下线、违规提交审核时，修改签约时间和店铺类型，不修改状态
        else {
            shopDetailMapper.updateById(newShopDetail);
        }
    }

    @Override
    public void exportShop(AuditingInfoParam auditingInfoParam, HttpServletResponse response) {
        List<ShopExportParam> shopExportList = shopDetailMapper.listExportByShopParam(auditingInfoParam);
        if (CollUtil.isEmpty(shopExportList)) {
            return;
        }
        ExcelWriter writer = ExcelUtil.getBigWriter();
        final List<String> exportCol = Arrays.asList(Objects.equals(I18nMessage.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang()) ? EXPORT_COL_CN : EXPORT_COL_EN);
        // 最大列数量
        int maxColNum = exportCol.size();

        Sheet sheet = writer.getSheet();
        // 设置列宽
        this.setColumnWidth(sheet);
        // 标题
        writer.merge(maxColNum - 1, Objects.equals(I18nMessage.getLang(), LanguageEnum.LANGUAGE_ZH_CN.getLang()) ? "店铺信息整理" : "Store information collation");
        // 列名
        writer.writeRow(exportCol);
        int rowIndex = 2;
        for (ShopExportParam shopExportParam : shopExportList) {
            int col = -1;
            // 店铺名称
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getShopName());
            // 商家名称
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getMerchantName());
            // 店铺状态
            ShopStatus shopStatus = ShopStatus.instance(shopExportParam.getShopStatus());
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, Objects.isNull(shopStatus) ? "" : shopStatus.text());
            // 联系电话
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getTel());
            // 邮箱
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getEmail());
            // 所在省份
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getProvince());
            // 所在城市
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getCity());
            // 所在区域
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getArea());
            // 详细地址
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getShopAddress());
            // 简介
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getIntro());
            // 创建时间
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getCreateTime());
            // 店铺类型
            ShopType shopType = ShopType.instance(shopExportParam.getType());
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, Objects.isNull(shopType) ? "" : shopType.text());
            // 签约起始时间
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getContractStartTime());
            // 签约终止时间
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getContractEndTime());
            // 经营范围
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getBusinessScope());
            // 统一社会信息代码
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getCreditCode());
            // 企业名称
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getFirmName());
            // 住所
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getResidence());
            // 法定代表人
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getRepresentative());
            // 注册资本（万元）
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getCapital());
            // 成立日期
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getFoundTime());
            // 营业起始日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, Objects.nonNull(shopExportParam.getStartTime()) ? sdf.format(shopExportParam.getStartTime()) : "");
            // 营业终止日期
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, Objects.nonNull(shopExportParam.getEndTime()) ? sdf.format(shopExportParam.getEndTime()) : "");
            ++rowIndex;
        }
        PoiExcelUtil.writeExcel(response, writer);
    }

    @Override
    public IPage<ShopHeadInfoDto> renovationShopPage(PageParam<ShopDetail> page, ShopSearchParam shopSearchParam) {
        return shopDetailMapper.renovationShopPage(page, shopSearchParam);
    }

    @Override
    public List<ShopHeadInfoDto> listRenovationShop(ShopSearchParam shopSearchParam) {
        if (CollUtil.isEmpty(shopSearchParam.getShopIds())) {
            return new ArrayList<>();
        }
        return shopDetailMapper.listRenovationShop(shopSearchParam);
    }

    @Override
    public List<ShopDetail> getShopDetailByShopIds(List<Long> shopIds) {
        return shopDetailMapper.getShopDetailByShopIds(shopIds);
    }


    private void setColumnWidth(Sheet sheet) {
        // 店铺名称
        sheet.setColumnWidth(0, 20 * 256);
        // 商家名称
        sheet.setColumnWidth(1, 20 * 256);
        // 店铺状态
        sheet.setColumnWidth(2, 20 * 256);
        // 联系电话
        sheet.setColumnWidth(3, 20 * 256);
        // 邮箱
        sheet.setColumnWidth(4, 20 * 256);
        // 所在省份
        sheet.setColumnWidth(5, 20 * 256);
        // 所在城市
        sheet.setColumnWidth(6, 20 * 256);
        // 所在区域
        sheet.setColumnWidth(7, 20 * 256);
        // 详细地址
        sheet.setColumnWidth(8, 60 * 256);
        // 简介
        sheet.setColumnWidth(9, 60 * 256);
        // 创建时间
        sheet.setColumnWidth(10, 20 * 256);
        // 店铺类型
        sheet.setColumnWidth(11, 20 * 256);
        // 签约起始时间
        sheet.setColumnWidth(12, 20 * 256);
        // 签约终止时间
        sheet.setColumnWidth(13, 20 * 256);
        // 经营范围
        sheet.setColumnWidth(14, 60 * 256);
        // 统一社会信息代码
        sheet.setColumnWidth(15, 20 * 256);
        // 企业名称
        sheet.setColumnWidth(16, 20 * 256);
        // 住所
        sheet.setColumnWidth(17, 30 * 256);
        // 法定代表人
        sheet.setColumnWidth(18, 20 * 256);
        // 注册资本（万元）
        sheet.setColumnWidth(19, 20 * 256);
        // 成立日期
        sheet.setColumnWidth(20, 20 * 256);
        // 营业起始日期
        sheet.setColumnWidth(21, 20 * 256);
        // 营业终止日期
        sheet.setColumnWidth(22, 20 * 256);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "shop_detail", key = "#shopId")
    public void auditApply(Long eventId, Long shopId, String reapplyReason) {
        ShopDetail shopDetail = shopDetailMapper.selectShopDetailById(shopId);
        if (Objects.isNull(shopDetail)) {
            // 未找到该店铺信息
            throw new YamiShopBindException("yami.store.not.exist");
        }
        if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            throw new YamiShopBindException("店铺状态已发生变化，请刷新后重试");
        }
        // 更新店铺状态为待审核状态
        shopDetailMapper.updateStatus(shopId, ShopStatus.OFFLINE_AUDIT.value());

        // 更新事件状态
        offlineHandleEventService.updateToApply(eventId, reapplyReason);
    }

    @Override
    public void computeShopScore(Long shopId) {
        if (Objects.isNull(shopId)) {
            return;
        }
        Date endTime = new Date();
        Date startTime = DateUtils.getBeforeDay(endTime, -180);
        List<ShopDetailVO> shopScoreList = prodCommService.computeShopScore(startTime, shopId);
        // 修改店铺评分
        // 没有一条评论,店铺评分为0
        if (shopScoreList.size() == 0) {
            ShopDetailVO shopDetailVO = new ShopDetailVO();
            shopDetailVO.setShopId(shopId);
            shopDetailVO.setShopScore(0.00);
            shopScoreList.add(shopDetailVO);
        }
        shopDetailMapper.batchUpdateShopScore(shopScoreList);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public String xsAccountOpening(Long shopId) {
        ShopDetail shopDetail = shopDetailMapper.selectShopDetailById(shopId);
        if (Objects.isNull(shopDetail)) {
            // 未找到该店铺信息
            throw new YamiShopBindException("yami.store.not.exist");
        }
        ShopCompany shopCompany = shopCompanyService.getOne(Wrappers.lambdaQuery(ShopCompany.class).eq(ShopCompany::getShopId, shopId).eq(ShopCompany::getStatus, AuditStatus.SUCCESSAUDIT.value()));
        if(ObjectUtil.isNull(shopDetail.getShopXsUserId())){
            List<ShopBankCard> shopBankCards = shopBankCardService.list(new LambdaQueryWrapper<ShopBankCard>().eq(ShopBankCard::getShopId, shopId).eq(ShopBankCard::getStatus, 1).eq(ShopBankCard::getIsDefault, 1));
            if (shopBankCards.isEmpty()) {
                throw new YamiShopBindException("yami.store.bankCard.not.exist");
            }
            ShopBankCard shopBankCard = shopBankCards.get(0);
            EnterpriseAccountOpeningParam enterpriseAccountOpeningParam = new EnterpriseAccountOpeningParam();
            enterpriseAccountOpeningParam.setShopId(shopId);
            // 企业名称
            enterpriseAccountOpeningParam.setUserName(shopCompany.getFirmName());
            // 企业为联系人手机号
            enterpriseAccountOpeningParam.setMobile(shopDetail.getReceiveMobile());
            // 证件类型
            enterpriseAccountOpeningParam.setCertType("2");
            // 证件号
            enterpriseAccountOpeningParam.setCertNo(shopCompany.getCreditCode());
            // 证件有效期 格式：YYYYMMDD 永久则输入21990101
            enterpriseAccountOpeningParam.setCertValidate(ObjectUtil.isNotNull(shopCompany.getEndTime()) ? DateUtil.format(shopCompany.getEndTime(), "YYYYMMDD") : "21990101");
            // 银行卡号企业为对公银行卡号
            enterpriseAccountOpeningParam.setCardNo(shopBankCard.getCardNo());
            // 银行简码
            enterpriseAccountOpeningParam.setBankCode(shopBankCard.getBankCode());
            // 开户行所属省份
            enterpriseAccountOpeningParam.setProvince(shopBankCard.getProvince());
            // 开户行所属城市
            enterpriseAccountOpeningParam.setCity(shopBankCard.getCity());
            // 开户支行
            enterpriseAccountOpeningParam.setBranch(shopBankCard.getOpeningBank());
            BaseTransForm base = hnaPayConfig.getR001TransForm(enterpriseAccountOpeningParam);
            try {
                Map<String, Object> responseMap = hnaPayConfig.post(base);
                if (responseMap.get("resultCode").equals("0000")) {
                    shopDetail.setShopXsUserId(responseMap.get("userId").toString());
                    shopDetail.setOpeningStatus(2);
                    shopDetailMapper.updateById(shopDetail);
                    shopBankCardService.setBindCardAgrNoByCardNo(responseMap.get("bindCardAgrNo").toString(), shopBankCard.getCardNo(), shopId);
                }

            } catch (Exception e) {
                return e.getMessage();
            }
        }
        // 上送企业证件资料
        String resourcesUrl = shopConfig.getDomain().getResourcesDomainName() + "/";
        Map<String, Object> certInfoMap = new HashMap<>();
        certInfoMap.put("1",resourcesUrl+shopCompany.getIdentityCardFront());
        certInfoMap.put("2",resourcesUrl+shopCompany.getIdentityCardLater());
        certInfoMap.put("4",resourcesUrl+shopCompany.getBusinessLicense());
        certInfoMap.put("7",resourcesUrl+shopCompany.getAccountOpeningLicense());
        for (Map.Entry<String, Object> entry : certInfoMap.entrySet()) {
            BaseTransForm baseTransForm = hnaPayConfig.getR003TransForm(shopDetail.getShopXsUserId(), entry.getKey());
            try {
                baseTransForm.setCertInfo(Base64Utils.encode(onlineImage2byte(entry.getValue().toString())));
                baseTransForm.setMerOrderId(baseTransForm.getMerOrderId() + entry.getKey());
                hnaPayConfig.post(baseTransForm);
            } catch (Exception e) {
                return e.getMessage();
            }
        }
        shopDetail.setOpeningStatus(3);
        shopDetailMapper.updateById(shopDetail);
        return "0000";
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopDetail.shopId")
    public String xsAccountOpeningUpload(Long shopId) {
        /**
         * 1-身份证正面；（企业必传）
         * 2-身份证反面；（企业必传）
         * 3-法人身份证手持；（非必传）
         * 4-营业执照；（企业必传）
         * 5-其他；（非必传）
         * 6-其他；（非必传）
         * 7-开户许可证；（企业必传）
         * 个人不需要上传，
         * 企业必传1，2，4，7
         */
        ShopCompany shopCompany = shopCompanyService.getOne(Wrappers.lambdaQuery(ShopCompany.class).eq(ShopCompany::getShopId, shopId).eq(ShopCompany::getStatus, AuditStatus.SUCCESSAUDIT.value()));
        if (Objects.isNull(shopCompany)) {
            throw new YamiShopBindException("店铺工商信息未找到，请刷新后重试");
        }
        String resourcesUrl = shopConfig.getDomain().getResourcesDomainName() + "/";
        Map<String, Object> certInfoMap = new HashMap<>();
        certInfoMap.put("1",resourcesUrl+shopCompany.getIdentityCardFront());
        certInfoMap.put("2",resourcesUrl+shopCompany.getIdentityCardLater());
        certInfoMap.put("4",resourcesUrl+shopCompany.getBusinessLicense());
        certInfoMap.put("7",resourcesUrl+shopCompany.getAccountOpeningLicense());
        ShopDetail shopDetail = shopDetailMapper.selectShopDetailById(shopId);
        for (Map.Entry<String, Object> entry : certInfoMap.entrySet()) {
            BaseTransForm base = hnaPayConfig.getR003TransForm(shopDetail.getShopXsUserId(), entry.getKey());
            try {
                base.setCertInfo(Base64Utils.encode(onlineImage2byte(entry.getValue().toString())));
                base.setMerOrderId(base.getMerOrderId() + entry.getKey());
                hnaPayConfig.post(base);
            } catch (Exception e) {
                return e.getMessage();
            }
        }
        shopDetail.setOpeningStatus(3);
        shopDetailMapper.updateById(shopDetail);
        return "0000";
    }

    @Override
    public void enterpriseChangeInfo(Long shopId) {
        ShopDetail shopDetail = shopDetailMapper.selectShopDetailById(shopId);
        ShopCompany shopCompany = shopCompanyService.getOne(Wrappers.lambdaQuery(ShopCompany.class).eq(ShopCompany::getShopId, shopId).eq(ShopCompany::getStatus, AuditStatus.SUCCESSAUDIT.value()));
        EnterpriseChangeInfoParam enterpriseChangeInfoParam = new EnterpriseChangeInfoParam();
        enterpriseChangeInfoParam.setUserId(shopDetail.getShopXsUserId());
        enterpriseChangeInfoParam.setCertNo(shopCompany.getCreditCode());
        enterpriseChangeInfoParam.setMobile(shopDetail.getReceiveMobile());
        enterpriseChangeInfoParam.setUserName(shopCompany.getFirmName());
        enterpriseChangeInfoParam.setCertValidate(ObjectUtil.isNotNull(shopCompany.getEndTime()) ? DateUtil.format(shopCompany.getEndTime(), "YYYYMMDD") : "21990101");
        BaseTransForm base = hnaPayConfig.getR011TransForm(enterpriseChangeInfoParam);
        try {
            hnaPayConfig.post(base);
        } catch (Exception e) {
            throw new YamiShopBindException(ResponseEnum.SHOW_FAIL,  e.getMessage());
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopDetail.shopId")
    public void auditNotice() {
        JSONObject reqParamJSON = requestKitBean.getReqParamJSON();
        String userId = reqParamJSON.getString("userId"); // 用户编号
        String auditResult = reqParamJSON.getString("auditResult"); // 审核结果
        String rejectReason = reqParamJSON.getString("rejectReason"); // 不通过原因
        String certTypeList = reqParamJSON.getString("certTypeList"); // 不通过证件类型列表
        ShopDetail shopDetail = shopDetailMapper.getShopDetailByXsUserId(userId);
        if (auditResult.equals("1")) {
            // 审核通过
            shopDetail.setOpeningStatus(1);
            shopDetail.setRemark(null);
            shopDetailMapper.updateById(shopDetail);
        } else {
            // 审核不通过
            shopDetail.setOpeningStatus(4);
            shopDetail.setRemark(rejectReason + "【" + certTypeList + "】");
            shopDetailMapper.updateById(shopDetail);
        }
    }

    @Override
    public List<ShopDetail> getSynchronizationDataList() {
        return shopDetailMapper.getSynchronizationDataList();
    }

    @Override
    public ShopDetail getShopDetailByShopCode(String shopCode) {
        return shopDetailMapper.getShopDetailByShopCode(shopCode);
    }


    @Override
    public String consumptionGasByShopId(Long shopId, Integer gas) {
        ShopDetail shopDetail = shopDetailMapper.selectById(shopId);
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("energy", gas.toString());
        paramMap.put("ioType", "0");
        paramMap.put("type", "3");
        String url = shopConfig.getApiGatewayUrl() + "/nft/outapi/nftUser/energyChangeForRomate";
        try {
            JSONObject jsonObject = dataWebService.hutoolPostWebService(url, paramMap, shopDetail.getApiUser(), shopDetail.getApiPassword());
            if (null == jsonObject || jsonObject.getInteger("code") != Constant.SUCCESS_CODE ) {
                throw new MailException(jsonObject.getString("msg"));
            }
            return "true";
        }catch (Exception e){
            String format = String.format("能量值扣减失败：%s", e.getMessage());
            log.error(format);
            return format;
        }
    }
    private Date getSaveEndOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.endOfDay(date));
        // 防止时间进位
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 检验店铺信息是否正确
     *
     * @param shopDetail 店铺基本信息
     * @param isCreate   true: 创建时校验， false: 更新时校验
     */
    private void checkShopInfo(ShopDetail shopDetail, Boolean isCreate) {
        String shopName = shopDetail.getShopName().trim();
        // 店铺名称
        if (StrUtil.isNotBlank(shopName)) {
            shopDetail.setShopName(shopDetail.getShopName().trim());
        } else {
            throw new YamiShopBindException(ResponseEnum.SHOW_FAIL, "yami.shop.name.not.blank");
        }
        if (shopDetailMapper.selectCount(Wrappers.lambdaQuery(ShopDetail.class).eq(ShopDetail::getShopName, shopDetail.getShopName()).ne(ShopDetail::getShopId, shopDetail.getShopId()).ne(ShopDetail::getShopStatus, ShopStatus.NOTOPEN.value())) > 0) {
            // 已有相同名称
            throw new YamiShopBindException(ResponseEnum.SHOW_FAIL, "yami.shop.name.have.already");
        }
        if (isCreate) {
            checkShopCode(shopDetail);
        } else {
            ShopDetail shop = getById(shopDetail.getShopId());
            if (StringUtils.isEmpty(shop.getChannelCode())) {
                checkShopCode(shopDetail);
            } else {
                if (!shop.getChannelCode().equals(shopDetail.getChannelCode())) {
                    throw new YamiShopBindException(ResponseEnum.SHOW_FAIL, "店铺编号不可修改！");
                }
            }
        }
    }

    private void checkShopCode(ShopDetail shopDetail) {
        boolean matching = PrincipalUtil.isMatching(PrincipalUtil.REGEXP_LOWERCASE, shopDetail.getChannelCode());
        if (!matching) {
            throw new YamiShopBindException(ResponseEnum.SHOW_FAIL, "编号不能为空，由2-4位的小写字母组成");
        }
        if (shopDetailMapper.selectCount(Wrappers.lambdaQuery(ShopDetail.class).eq(ShopDetail::getChannelCode, shopDetail.getChannelCode()).ne(ShopDetail::getShopId, shopDetail.getShopId()).ne(ShopDetail::getShopStatus, ShopStatus.NOTOPEN.value())) > 0) {
            // 已有相同名称
            throw new YamiShopBindException(ResponseEnum.SHOW_FAIL, "已有相同店铺编号");
        }
    }

    /**
     * 添加店铺钱包信息
     *
     * @param shopId
     */
    private void addShopInfo(Long shopId) {
        ShopWallet shopWallet = new ShopWallet();
        shopWallet.setShopId(shopId);
        shopWallet.setUnsettledAmount(0.0);
        shopWallet.setSettledAmount(0.0);
        shopWallet.setFreezeAmount(0.0);
        shopWallet.setTotalSettledAmount(0.0);
        shopWallet.setVersion(0L);
        shopWallet.setUpdateTime(new Date());
        shopWalletMapper.insert(shopWallet);
    }

    /**
     * 发送事件提醒es更新商品信息
     *
     * @param shopIds
     */
    private void updateProdByShopIds(List<Long> shopIds) {
        List<Long> prodIds = productMapper.listIdByShopIds(shopIds);
        if (CollUtil.isEmpty(prodIds)) {
            return;
        }
        eventPublisher.publishEvent(new EsProductUpdateEvent(null, prodIds, EsOperationType.UPDATE_BATCH));
    }


    /**
     * 线上图片转为byte数组
     *
     * @param path
     * @return
     */
    private static byte[] onlineImage2byte(String path) throws IOException {
        byte[] data;
        URL url;
        InputStream input;
        try {
            url = new URL(path);
            HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            httpUrl.getInputStream();
            input = httpUrl.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        int numBytesRead = 0;
        while ((numBytesRead = input.read(buf)) != -1) {
            output.write(buf, 0, numBytesRead);
        }
        data = output.toByteArray();
        output.close();
        input.close();
        return data;
    }
    @Override
    public List<String> getAllShopShortNameList() {
        return shopDetailMapper.getAllShopShortNameList();
    }
}
